//
//  DeinitializationTest.swift
//  BJ12366Swift
//
//  Created by ZRAR on 16/2/29.
//  Copyright © 2016年 ZRAR. All rights reserved.
//

import UIKit

class DeinitializationTest: NSObject {

    //析构过程
    deinit{
        
        //执行析构过程
    }
    
    struct Bank {
        
        static var coinslnBank = 10_000
        static func vendCoins(var numberOfCoinsToVend:Int)->Int{
            
            numberOfCoinsToVend = min(numberOfCoinsToVend, coinslnBank)
            coinslnBank -= numberOfCoinsToVend
            
            return numberOfCoinsToVend
        }
        static func receiveCoins(coins:Int){
            coinslnBank += coins
        }
    }
    class Player {
        var coinsInPurse:Int
        init(coins:Int){
            
            coinsInPurse = Bank.vendCoins(coins)
        }
        func winCoins(coins:Int){
            coinsInPurse += Bank.vendCoins(coins)
        }
        deinit{
            Bank.receiveCoins(coinsInPurse)
        }
    }
    //类实例之间的循环强引用
    class Person {
        let name:String
        init(name:String){self.name = name}
        var apartment:Apartment?
        deinit{print("\(name) is being deinitialized")}
    }
    class Apartment {
        
        let unit:String
        init(unit:String){self.unit = unit}
       weak var tenant:Person?
        deinit{print("Apartment \(unit) is being deinitialized")}
        
    }
    
    func calssCirculationQuote(){
        
        var john:Person?
        var unit4A:Apartment?
        john = Person(name: "John Appleseed")
        unit4A = Apartment(unit: "4A")
        john?.apartment = unit4A
        unit4A?.tenant = john
        
    }
    //两种方法解决循环强引用：弱引用（关键字 weak）和无主引用(关键字 unowned)
    //无主引用是永远有值的，因此，总是被定义为非可选类型
    //Customer 和 CreditCard的关系，一个客户可能有或者没有信用卡，但是一张信用卡总是关联着一个客户
    //Customer有一个可选类型的card属性，但是CreditCard类有一个非可选类型的customer属性
    class Customer {
        let name:String
        var card:CreditCard?
        init(name:String){
            
            self.name = name
        }
        deinit{print("\(name) is being deinitialized")}
    }
    class CreditCard {
        let number:UInt64
        unowned let customer:Customer
        init(number:UInt64, customer:Customer){
            
            self.number = number
            self.customer = customer
        }
    }
    //两个属性都必须有值，并且初始化完成后永远不会为nil.这种情况需要一个类使用无主属性，另外一个类使用隐式解析可选属性
    class Country {
        let name:String
        var capitalCity:City!
        init(name:String,capitalName:String){
            self.name = name;
            self.capitalCity = City(name: capitalName, country: self)
        }
    }
    class City {
        let name:String
        unowned let country:Country
        init(name:String,country:Country){
            self.name = name
            self.country = country
        }
    }
    //解决闭包引起的循环强引用
    //在闭包和捕获的实例总是相互引用时并且总是同时销毁时，将闭包内的捕获定义为无主引用
    //在被捕获的引用可能变为nil时，将闭包内的捕获定义为弱引用。
    class HTMLElement {
        let name:String
        let text:String?
        lazy var asHTML:Void ->String={
            [unowned self]in
            if let text = self.text{
                return "<\(self.name)>\(text)</\(self.name)>"
            }else{
                
                return "<\(self.name)/>"
            }
            
        }
        init(name:String,text:String?=nil){
            self.name = name;
            self.text = text
        }
        deinit{
            print("\(name) is being deinitialized")
        }
    }
    func HTMLTest(){
        
        var paragraph:HTMLElement = HTMLElement(name: "p", text: "hello,world")
        print(paragraph.asHTML())
    }
    
}

